package ar.uba.fi.tonyvaliente.commands;

import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.io.filefilter.WildcardFileFilter;

import ar.uba.fi.tonyvaliente.documents.AddDocumentResult;
import ar.uba.fi.tonyvaliente.documents.DocumentManager;
import ar.uba.fi.tonyvaliente.signature.HashFunction;
import ar.uba.fi.tonyvaliente.signature.SignatureConfiguration;
import ar.uba.fi.tonyvaliente.signature.SignatureConfigurationException;
import ar.uba.fi.tonyvaliente.signature.process.CreateSignatureResult;
import ar.uba.fi.tonyvaliente.signature.process.SignatureGenerator;
import ar.uba.fi.tonyvaliente.utils.RecursosAplicacion;

public class CreateSignaturesCommand extends Command {

	private boolean recognized;
	private String path;
	private String[] patterns;
	private List<HashFunction> hashFunctions;
	private int length;
	private String configurationPath;

	public CreateSignaturesCommand(String[] args) {
		super(args);

		recognized = false;
		path = null;
		patterns = null;

		if (args.length > 0) {
			String command = args[0];
			command = command.toLowerCase();
			if (command.equals("-createsignatures")) {
				recognized = true;
				if (args.length > 1) {
					configurationPath = RecursosAplicacion.instance().getProperty("hash.config");
					path = args[1];
				}
				if (args.length > 3) {
					patterns = new String[args.length - 3];
					for (int i = 0; i < patterns.length; i++) {
						patterns[i] = args[i + 3];
					}
				}
			}
		}
	}

	private CommandResult createSignatures() {
		boolean success = true;
		StringBuffer errorMessage = new StringBuffer();

		SignatureConfiguration config = null;
		try {
			config = SignatureConfiguration.loadFromFile(configurationPath);
		} catch (SignatureConfigurationException e) {
			e.printStackTrace();
			return new CommandResult(true, false, e.getMessage());
		}
		hashFunctions = new ArrayList<HashFunction>(config.getHashFunctions());
		length = config.getSignatureLength();
		
		
		
		File directory = new File(path);
		String[] files = directory.list(new PatternFilter(patterns));
		for (int i = 0; i < files.length; i++) {
			File file = new File(path + "/" + files[i]);
			if (!file.isFile())
				continue;

			CreateSignatureResult createSignatureResult = SignatureGenerator
						.process(file.getAbsolutePath(), hashFunctions, length);
			if (!createSignatureResult.isSuccess()) {
				success = false;
				errorMessage.append(createSignatureResult.getErrorMessage());
				errorMessage.append("\n");
			}
		}

		if (success)
			return CommandResult.EXECUTE_SUCCESSFULLY;
		else
			return new CommandResult(true, false, errorMessage.toString());
	}

	public CommandResult execute() {
		if (!recognized)
			return CommandResult.NOT_RECOGNIZED;

		if (path == null)
			return new CommandResult(true, false, "Missing directory's path");

		if (!directoryExists(path))
			return new CommandResult(true, false, "Directory not exists");

		return createSignatures();
	}

	public String getSignature() {
		return "-createSignatures \"path to config file\" \"path to directory\" [filters]";
	}

	public String getDescription() {
		return "Creates the signature for all the documents contained in the directory";
	}

	public String[] getExamples() {
		return new String[] {
				String.format("-createSignatures \"/var/local/config/config.properties\" \"%s\"", "/var/local/documents"),
				String.format("-createSignatures \"/var/local/config/config.properties\" \"%s\" \"%s\" \"%s\"",
						"/var/local/documents", "*.htm", "*.html") };
	}

	private static boolean directoryExists(String path) {
		File file = new File(path);
		return file.exists() && file.isDirectory();
	}

	private class PatternFilter implements FilenameFilter {
		private String[] patterns;

		public PatternFilter(String[] patterns) {
			this.patterns = patterns;
		}

		public boolean accept(File dir, String name) {
			if (patterns == null || patterns.length == 0)
				return true;

			for (int i = 0; i < patterns.length; i++) {
				FileFilter fileFilter = new WildcardFileFilter(patterns[i]);
				if (fileFilter.accept(new File(name))) {
					return true;
				}
			}

			return false;
		}
	}
}
